package com.healthcarex.hip.saas.security.service.impl;

import com.healthcarex.hip.saas.common.model.BaseModel;
import com.healthcarex.hip.saas.security.dao.UserDao;
import com.healthcarex.hip.saas.security.dao.UserDeptDao;
import com.healthcarex.hip.saas.security.dao.UserRoleDao;
import com.healthcarex.hip.saas.security.model.SysUser;
import com.healthcarex.hip.saas.security.model.SysUserDept;
import com.healthcarex.hip.saas.security.model.SysUserRole;
import com.healthcarex.hip.saas.security.model.UserWithRole;
import com.healthcarex.hip.saas.security.service.IUserService;
import com.healthcarex.hip.saas.security.util.SecurityUtils;
import com.healthcarex.hip.saas.mybatis.service.impl.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @author chenpan
 * @ClassName: UserServiceImpl
 * description:
 * @date 2018-04-02 1:30
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<SysUser> implements IUserService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private UserRoleDao userRoleDao;

    @Autowired
    private UserDeptDao userDeptDao;

    @Override
    public UserWithRole findById(Integer userId) {
        UserWithRole userWithRole = this.userDao.findUserWithRole(userId);

        return userWithRole;
    }

    @Override
    public SysUser findByName(String userName) {
        Example example = new Example(SysUser.class);
        example.createCriteria().andCondition("lower(username)=", userName.toLowerCase());
        List<SysUser> list = this.selectByExample(example);
        if (list.size() == 0) {
            return null;
        } else {
            return list.get(0);
        }
    }

    @Override
    public List<UserWithRole> findUsers(SysUser user) {
        return this.userDao.findUsers(user);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
    public void registUser(SysUser user) {
        user.setId(this.getSequence(BaseModel.BASE_SEQ));
        user.setCreateTime(new Date());
        user.setTheme(SysUser.DEFAULT_THEME);
        user.setAvatar(SysUser.DEFAULT_AVATAR);
        user.setPassword(BCrypt.hashpw(user.getPassword(), BCrypt.gensalt()));
        this.save(user);

        //分配默认权限
      /*  SysUserRole ur = new SysUserRole();
        ur.setUserId(user.getId());

        this.userRoleDao.insert(ur);*/
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
    public void updateTheme(String theme, String userName) {
        Example example = new Example(SysUser.class);
        example.createCriteria().andCondition("username=", userName);
        SysUser user = new SysUser();
        user.setTheme(theme);
        this.userDao.updateByExampleSelective(user, example);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
    public void addUser(SysUser user, Integer[] roles, Integer[] depts) {
        user.setId(this.getSequence(BaseModel.BASE_SEQ));
        user.setCreateTime(new Date());
        user.setCreateBy(SecurityUtils.getUsername());
        user.setDeleteFlag("0");
        user.setTheme(SysUser.DEFAULT_THEME);
        user.setAvatar(SysUser.DEFAULT_AVATAR);
        user.setPassword(BCrypt.hashpw(user.getPassword(), BCrypt.gensalt()));
        this.save(user);
        if (roles != null) {
            for (Integer roleId : roles) {
                SysUserRole ur = new SysUserRole();
                ur.setUserId(user.getId());
                ur.setRoleId(roleId);
                this.userRoleDao.insertSelective(ur);
            }
        }
        if (depts != null) {
            for (Integer deptId : depts) {
                SysUserDept ud = new SysUserDept();
                ud.setUserId(user.getId());
                ud.setDeptId(deptId);
                this.userDeptDao.insertSelective(ud);
            }
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
    @CacheEvict(value = {"authority", "urlPermission"}, allEntries = true)
    public void updateUser(SysUser user, Integer[] roles, Integer[] depts) {
        user.setPassword(null);
        user.setUsername(null);
        user.setUpdateTime(new Date());
        user.setUpdateBy(SecurityUtils.getUsername());
        this.updateNotNull(user);

        // 删除原有用户角色
        Example example = new Example(SysUserRole.class);
        example.createCriteria().andCondition("user_id=", user.getId());
        this.userRoleDao.deleteByExample(example);

        // 删除原有用户科室
        Example example2 = new Example(SysUserDept.class);
        example2.createCriteria().andCondition("user_id=", user.getId());
        this.userDeptDao.deleteByExample(example2);

        // 新增用户角色
        if (roles != null) {
            for (Integer roleId : roles) {
                SysUserRole ur = new SysUserRole();
                ur.setUserId(user.getId());
                ur.setRoleId(roleId);
                this.userRoleDao.insertSelective(ur);
            }
        }

        // 新增用户科室
        if (depts != null) {
            for (Integer deptId : depts) {
                SysUserDept ud = new SysUserDept();
                ud.setUserId(user.getId());
                ud.setDeptId(deptId);
                this.userDeptDao.insertSelective(ud);
            }
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
    public void deleteUsers(String userIds) {
        List<String> list = Arrays.asList(userIds.split(","));

        Example example = new Example(SysUserRole.class);
        example.createCriteria().andIn("userId", list);
        // 删除 用户角色
        this.userRoleDao.deleteByExample(example);


        example = new Example(SysUserDept.class);
        example.createCriteria().andIn("userId", list);
        // 删除用户科室
        this.userDeptDao.deleteByExample(example);

        //删除用户
        this.batchDelete(list, "id", SysUser.class);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
    public void updateLoginTime(String userName) {
        Example example = new Example(SysUser.class);
        example.createCriteria().andCondition("lower(username)=", userName.toLowerCase());
        SysUser user = new SysUser();
        user.setLastLoginTime(new Date());
        this.userDao.updateByExampleSelective(user, example);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
    @CacheEvict(value = "user", key = "#p0")
    public void updatePassword(Integer userId, String password) {
        Example example = new Example(SysUser.class);
        example.createCriteria().andCondition("id=", userId);
        SysUser user = new SysUser();
        user.setPassword(BCrypt.hashpw(password, BCrypt.gensalt()));
        this.userDao.updateByExampleSelective(user, example);
    }

    @Override
    public SysUser findUserProfile(SysUser user) {
        return this.userDao.findUserProfile(user);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
    @CacheEvict(value = "user", key = "#p0.id")
    public void updateUserProfile(SysUser user) {
        user.setUsername(null);
        user.setPassword(null);
        user.setUpdateTime(new Date());
        user.setUpdateBy(SecurityUtils.getUsername());

        this.updateNotNull(user);
    }

    @Override
    @Cacheable(value = "user", key = "#p0")
    public SysUser findUser(Integer userId) {
        return userDao.selectByPrimaryKey(userId);
    }
}
